home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / misc / amag / 9301b.lha / Devices (Folge 3) / Terminal0.c < prev    next >
C/C++ Source or Header  |  1992-04-18  |  11KB  |  398 lines

  1. /* Terminal0.c
  2.  
  3.    Autor: E.G. Meyzis, Mai 1992
  4.  
  5.    Compile Instr. fuer DICE:                  execute cterm0
  6.    dcc Terminal0.c -c -o t:Terminal0.o
  7.  
  8.    Link Instr. fuer DICE:                     execute lterm0
  9.    dlink dlib:c.o t:Terminal0.o dlib:c.lib+
  10.    dlib:amigas20.lib dlib:auto.lib dlib:x.o -o Terminal0
  11. */
  12.  
  13. #include <Devices/Serial.h>
  14. #include <Dos/Dos.h>
  15. #include <Dos/DosExtens.h>
  16. #include <Exec/Exec.h>
  17. #include <Intuition/Intuition.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20.  
  21. /* +++++++++  Definitionen  ++++++++++++
  22. */
  23. #define TRUE  1   /* um mit dem Datentyp BOOL zu arbeiten */
  24. #define FALSE 0
  25.  
  26.       /* zwei Definitionen fuer DOS-Fenster */
  27.  
  28. #define TxTitle "CON:0/0/500/100/ Terminal-Send "
  29. #define RxTitle "CON:0/101/500/100/ Terminal-Receive "
  30.  
  31.       /* Texte zur Info bei Text-Senden/Empfangen */
  32.  
  33. #define Senden   "\nSende Textdatei\n\n"
  34. #define Empfang  "\nwarte auf Textdatei\n\n"
  35. #define Beendet  "\nÜbertragung beendet\n\n"
  36.  
  37. #define Unit0     0      /* eingebaute ser. Schnittstelle */
  38. #define PLaenge 512      /* Pufferlaenge Datemuebertrag.  */
  39.  
  40. struct GetBlock             /* nur in GetWinPtr verwendet */
  41.          {
  42.           struct StandardPacket stdPkt;
  43.           struct InfoData       info;
  44.          };
  45.  
  46. /* +++++++++  Datentypen  ++++++++++++
  47. */
  48. typedef char                BOOL;
  49. typedef char                *CharPtr;
  50. typedef struct IOExtSer     *IOExtSerPtr;
  51. typedef struct FileHandle   *FileHandleBPtr;      /* BPTR */
  52. typedef struct FileHandle   *FileHandlePtr;    /* Adresse */
  53. typedef struct Window       *WindowPtr;
  54. typedef struct GetBlock     *GetBlockPtr;
  55. typedef struct MessagePort  *MsgPortPtr;
  56. typedef struct IntuiMessage *IntuiMessagePtr;
  57.  
  58.  
  59. APTR GetSysBase();    /* Adr ExecBase aus Adresse 4 holen */
  60.  
  61. void GetWinPointer (FileHandleBPtr *winHdl,
  62.                     WindowPtr      *winPtr);
  63. void MakeWindow(CharPtr        namePtr,
  64.                 WindowPtr      *winPtr,
  65.                 FileHandleBPtr *fileHdl);
  66. BOOL WindowsAngelegt();
  67.  
  68. void SetBaudRate(IOExtSerPtr serPtr);
  69. BOOL InitSerialDev(IOExtSerPtr serPtr, int cmnd);
  70. BOOL SerialVorbereitet();
  71. void SetTermChars(IOExtSerPtr serPtr);
  72. void FlushSerialDevice();
  73.  
  74. void SendeTextDatei(IOExtSerPtr txReqPtr);
  75. void EmpfangeTextDatei(IOExtSerPtr rxReqPtr);
  76.  
  77. void TerminalLoop();
  78. void Aufraeumen();
  79.  
  80. /* +++++++++  globale Variablen  ++++++++++++
  81. */
  82. struct ExecBase *execBasePtr;
  83.  
  84. /*
  85.                Doppelt ausgelegte Datenstrukturen
  86.  
  87.                 Sendeteil:         Empfangsteil:
  88. */
  89.                 /* Device zweimal oeffnen */
  90. struct IOExtSer txRequest,         rxRequest;
  91.  
  92.                 /* jedem Device seinen Puffer */
  93. char            rxPuffer[PLaenge], txPuffer[PLaenge];
  94.  
  95.                 /* getrennte Fenster fuer Ein-/Ausgaben */
  96. FileHandleBPtr  txWin,             rxWin;
  97. WindowPtr       txWinPtr,          rxWinPtr;
  98.  
  99.  
  100.  
  101. APTR GetSysBase() /* Adr ExecBase aus Adresse 4 holen */
  102. {
  103.  long *systemBasis;
  104.  
  105.  systemBasis = (APTR)4;
  106.  return (APTR)*systemBasis;
  107. }
  108.  
  109.  
  110. /* Mit Dos.Open geoeffnete Fenster liefern nur einen Handle
  111.    und leider nicht den WindowPtr; deshalb:
  112. */
  113. void GetWinPointer (FileHandleBPtr *winHdl,
  114.                     WindowPtr      *winPtr)
  115. {
  116.  MsgPortPtr  portPtr;
  117.  GetBlockPtr pktPtr;
  118.  
  119.  FileHandlePtr wHdlPtr;
  120.  
  121.  *winPtr = NULL;                   /* negatives Vorurteil */
  122.  if (IsInteractive(*winHdl))        /* Fenster vorhanden? */
  123.    {
  124.     wHdlPtr = (APTR)((long)*winHdl) << 2;  /* BPTR -> Adr */
  125.     if (portPtr = (MsgPortPtr)CreateMsgPort())
  126.       {
  127.        /* Speicher fuer Dos.Packet anfordern*/
  128.  
  129.        pktPtr=(GetBlockPtr)AllocMem(sizeof(struct GetBlock),
  130.                                     MEMF_CLEAR|MEMF_PUBLIC);
  131.        if (pktPtr)           /* Dos.Packet initialisieren */
  132.          {
  133.           pktPtr->stdPkt.sp_Pkt.dp_Link =
  134.                                      &pktPtr->stdPkt.sp_Msg;
  135.           pktPtr->stdPkt.sp_Pkt.dp_Port = portPtr;
  136.           pktPtr->stdPkt.sp_Pkt.dp_Type = ACTION_DISK_INFO;
  137.           pktPtr->stdPkt.sp_Pkt.dp_Arg1 = &pktPtr->info >>2;
  138.           pktPtr->stdPkt.sp_Msg.mn_Node.ln_Name =
  139.                                      &pktPtr->stdPkt.sp_Pkt;
  140.           pktPtr->stdPkt.sp_Msg.mn_Node.ln_Type= NT_MESSAGE;
  141.           pktPtr->stdPkt.sp_Msg.mn_Length =
  142.                                      sizeof(struct Message);
  143.  
  144.           PutMsg(wHdlPtr->fh_Type, pktPtr);/*und absenden */
  145.           do
  146.             WaitPort(portPtr);     /* auf Antwort von Dos */
  147.           while (APTR)GetMsg(portPtr) != pktPtr;
  148.  
  149.           if (pktPtr->stdPkt.sp_Pkt.dp_Res1)/* Antwort ok */
  150.              *winPtr = (APTR)pktPtr->info.id_VolumeNode;
  151.  
  152.            DeleteMsgPort(portPtr);
  153.            FreeMem(pktPtr, sizeof(struct GetBlock));
  154.          }
  155.        else
  156.          DeleteMsgPort(portPtr);
  157.       }
  158.  
  159.    } /* Interactive */
  160. }
  161.  
  162.  
  163. /* Dos.Fenster anlegen und WindowPtr holen */
  164.  
  165. void MakeWindow(CharPtr        namePtr,
  166.                 WindowPtr      *winPtr,
  167.                 FileHandleBPtr *fileHdl)
  168.  
  169. {
  170.   *fileHdl = (FileHandleBPtr)Open(namePtr, MODE_NEWFILE);
  171.   if (*fileHdl)
  172.     GetWinPointer(&(*fileHdl), &(*winPtr));
  173. }
  174.  
  175.  
  176. /* Beide Terminal-Fenster anlegen und bei Fehlschlag
  177.    Ressourcen freigeben.
  178. */
  179. BOOL WindowsAngelegt()
  180. {
  181.   BOOL angelegt;
  182.  
  183.   angelegt = FALSE;         /* zunaechst keines vorhanden */
  184.  
  185.   MakeWindow(TxTitle, &txWinPtr, &txWin);/* Sende-Fenster */
  186.   if (txWinPtr)
  187.     {
  188.      angelegt = TRUE;
  189.  
  190.      /* um Tastatureingaben durch Intuition abzufangen */
  191.  
  192.      ModifyIDCMP(txWinPtr, IDCMP_RAWKEY|IDCMP_VANILLAKEY);
  193.  
  194.      MakeWindow(RxTitle, &rxWinPtr, &rxWin);/*Empf.-Fenst */
  195.      if (rxWinPtr = NULL)
  196.        {
  197.         angelegt = FALSE;        /* Sendefenster aufgeben */
  198.         Close(txWin);
  199.         txWin = NULL;
  200.        }
  201.     }
  202.   else                    /* WindowPtr nicht zu ermitteln */
  203.     if (txWin)
  204.        Close(txWin);                /* deshalb schliessen */
  205.   return angelegt;
  206. }
  207.  
  208. /* 3. Erweiterung Listing 3-3 hier einsetzen */
  209.  
  210. /* 4. Erweiterung Listing 3-4 hier einbauen */
  211.  
  212.  
  213. /* Device-Struktur initialisieren und Device oeffnen */
  214.  
  215. BOOL InitSerialDev(IOExtSerPtr serPtr, int cmnd)
  216. {
  217.   MsgPortPtr  portPtr;
  218.   BOOL        erfolg;
  219.  
  220.   erfolg = FALSE;
  221.   portPtr = (MsgPortPtr)CreateMsgPort();   /* fuer Device */
  222.   if (portPtr)
  223.     {
  224.      serPtr->io_SerFlags = SERF_SHARED; /* Mehrfachutzung */
  225.      serPtr->IOSer.io_Length = 1;/* 1 Byte lesen/schreib. */
  226.      serPtr->IOSer.io_Message.mn_ReplyPort = portPtr;
  227.  
  228.      OpenDevice(SERIALNAME, Unit0, serPtr, 0);
  229.      if (serPtr->IOSer.io_Error != IOERR_OPENFAIL)
  230.        {
  231.         erfolg = TRUE;
  232.  
  233.         /* 3. Erweiterung Listing 3-3 hier aufrufen
  234.            SetBaudRate(serPtr);
  235.         */
  236.         serPtr->IOSer.io_Command = cmnd;/* CMD_WRITE/READ */
  237.        }
  238.       else                     /* Device nicht zu oeffnen */
  239.        {
  240.         DeleteMsgPort
  241.                     (serPtr->IOSer.io_Message.mn_ReplyPort);
  242.         serPtr->IOSer.io_Message.mn_ReplyPort = NULL;
  243.        }
  244.     }
  245.   return erfolg;
  246. }
  247.  
  248.  
  249. BOOL SerialVorbereitet() /* getrennte Devices als  Sende- */
  250. {                        /* Empfangskanal oeffnen */
  251.   BOOL vorbereitet;
  252.  
  253.   if (InitSerialDev(&txRequest, CMD_WRITE)) /* Sendekanal */
  254.     {
  255.      vorbereitet = TRUE;
  256.      txRequest.IOSer.io_Data=txPuffer;/*f. Dateiuebertrag.*/
  257.  
  258.      if (InitSerialDev(&rxRequest, CMD_READ))/*Empf.-Kanal*/
  259.        {
  260.         rxRequest.IOSer.io_Data = rxPuffer; /* ext. Puffer*/
  261.        }
  262.      else                /* kein Empfangskanal zu oeffnen */
  263.        {
  264.         vorbereitet = FALSE;
  265.         DeleteMsgPort
  266.                   (txRequest.IOSer.io_Message.mn_ReplyPort);
  267.         txRequest.IOSer.io_Message.mn_ReplyPort = NULL;
  268.        }
  269.     }
  270.   else/*kein Kanal zu oeffnen; Device evtl exklusiv belegt*/
  271.     vorbereitet = FALSE;
  272.  
  273.   return vorbereitet;
  274. }
  275.  
  276.  
  277. /* 5. Erweiterung Listing 3-5 hier einbauen */
  278.  
  279. /* 6. Erweiterung Listing 3-6 hier einbauen */
  280.  
  281. /* 6. Erweiterung Listing 3-6 */
  282.  
  283.  
  284. void TerminalLoop()           /* Hauptschleife  des Prog. */
  285. {
  286.   IntuiMessagePtr inMsgPtr;  /* fuer IDCMP-Nachr. aus dem */
  287.   long            klasse,                 /* Sendefenster */
  288.                   done,
  289.                   txSig, /*aus UserPort des Sendefensters */
  290.                   rxSig,  /* aus Empfangs-Device-Struktur */
  291.                   erwartSig, /* Kombination txSig | rxSig */
  292.                   erhaltSig;       /* angekommene Signale */
  293.   int             raw;             /* fuer Tastatur-Codes */
  294.  
  295.   txSig = 1 << txWinPtr->UserPort->mp_SigBit;
  296.   rxSig = 1 <<
  297.          rxRequest.IOSer.io_Message.mn_ReplyPort->mp_SigBit;
  298.   erwartSig = txSig | rxSig;
  299.  
  300.   SendIO(&(rxRequest));  /* async. aufs 1. Zeichen warten */
  301.   for(;;)
  302.     {
  303.      erhaltSig = Wait(erwartSig);  /* Tastendruck/Empfang */
  304.      if (txSig & erhaltSig) /*Taste im Sendefenster gedr. */
  305.        {
  306.         inMsgPtr = (IntuiMessagePtr)      /* Msg. abholen */
  307.                    GetMsg(txWinPtr->UserPort);
  308.  
  309.         klasse = inMsgPtr->Class;   /* copy Msg teilweise */
  310.         raw    = inMsgPtr->Code;
  311.  
  312.         ReplyMsg(inMsgPtr);            /* Msg beantworten */
  313.  
  314.         if (IDCMP_VANILLAKEY & klasse)   /* ASCII-Zeichen */
  315.           {
  316.            txPuffer[0] = raw;  /* Zeichen in Sende-Puffer */
  317.            if (txPuffer[0] != 033) /* nicht ESC gedrueckt */
  318.              {
  319.               done = Write(txWin, txPuffer, 1);   /* Echo */
  320.               DoIO(&txRequest);         /* Zeichen senden */
  321.              }
  322.            else                          /* ESC gedrueckt */
  323.              break;                 /* Programm abbrechen */
  324.           }
  325.        else
  326.          if (IDCMP_RAWKEY & klasse) /* z.B. F1 - F10 gedr.*/
  327.            {
  328.             if ((raw >= 80) && (raw <= 89))
  329.               {
  330.               /* Funktionstasten auswerten F1 - F10 */
  331.                if (raw == 80)
  332.                  {                       /* F1 */
  333.                   /* 5. Erweiterung
  334.                      Aufruf SendeTextDatei(txRequest);
  335.                      aus Listing 3-5 hier einfuegen
  336.                   */
  337.                  }
  338.                 else
  339.                   if (raw == 81)                    /* F2 */
  340.                     {
  341.                      /* 6. Erweiterung
  342.                         Aufruf EmpfangeTextDatei(rxRequest);
  343.                         aus Listing 3-6 hier einfuegen
  344.                      */
  345.                     }
  346.               } /* raw >= 80*/
  347.            } /* IDCMP_RAWKEY */
  348.        } /* txSig */
  349.      if (rxSig & erhaltSig)/* mind. 1 Zeich. im Empf-kanal*/
  350.        {
  351.         WaitIO(&rxRequest);             /* dieses abholen */
  352.         if (rxRequest.IOSer.io_Error == 0)
  353.            done = Write(rxWin, rxPuffer, 1);/*u. ausgeben */
  354.  
  355.         /* 2. Erweiterung gem Listing 3-2 hier einfuegen */
  356.  
  357.         SendIO(&rxRequest); /* aufs naechste Zeich. wart. */
  358.        }
  359.     } /* for */
  360.     AbortIO(&rxRequest);   /* Auftrag an Device abbrechen */
  361.     WaitIO(&rxRequest);
  362. }
  363.  
  364. /* 1. Erweiterung  FlushSerialDevice;
  365.    Listing 3-1 hier einbauen
  366. */
  367.  
  368. void Aufraeumen()
  369. {
  370.   DeleteMsgPort(rxRequest.IOSer.io_Message.mn_ReplyPort);
  371.   CloseDevice(&rxRequest);
  372.   DeleteMsgPort(txRequest.IOSer.io_Message.mn_ReplyPort);
  373.   CloseDevice(&txRequest);
  374.   Close(rxWin);
  375.   Close(txWin);
  376.   /* 1. Erweiterung
  377.      Aufruf FlushSerialDevice aus
  378.      Listing 3-1 hier vornehmen
  379.   */
  380. }
  381.  
  382. int main()
  383. {
  384.  BOOL done;
  385.  
  386.  execBasePtr = GetSysBase();   /* Adr ExecBase beschaffen */
  387.  
  388.  if (execBasePtr->LibNode.lib_Version >= 36) /* ja, OS 2  */
  389.   {
  390.    if (WindowsAngelegt() && SerialVorbereitet())
  391.      {
  392.       TerminalLoop();     /* Steuerschleife des Programms */
  393.       Aufraeumen();
  394.      }
  395.   }
  396.   return 0;
  397. }
  398.